/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "材质节点.h"
#include "节点/节点树.h"
#include "节点/socket_utils.h"

#include "../插座/材质纹理插座.h"
#include "../插座/C_数值插座.h"
#include "../插座/list/list物体插座.h"

#include "../../node后端.h"

#include "异步解算/物理异步解算.h"
#include "材质纹理JIT函数绑定.h"

#include <JIT.h>


static std::string g材质_参数 = "g材质_参数";



//static std::string f_着色器输出节点编译回调(C_节点基类* self, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
//	self->m_Code = "";
//	self->m_ReleaseCode = "";
//
//	std::string Color = "Color";
//	self->m_Code += "vec3 " + Color + " = f_MaterialPBR_calc(material, gl_WorldRayDirectionEXT, LigthDir, normal, hitValue);\n";
//	self->m_Code += "hitValue.Color = mix(hitValue.Color, " + Color + ", 0.6);\n";
//
//
//	self->f_get输出插座(1)->f_setCode(Color);
//
//	return self->m_Code;
//}

static std::string f_着色器引用数据声明() {
	std::string code;
	code += "R_GlobalParameter_I32 i32_GParam = R_GlobalParameter_I32(gGlobalParam.m_AddressI32);\n";
	code += "R_GlobalParameter_F32 f32_GParam = R_GlobalParameter_F32(gGlobalParam.m_AddressF32);\n";
	code += "R_GlobalParameter_Vec2 vec2_GParam = R_GlobalParameter_Vec2(gGlobalParam.m_AddressVec2);\n";
	code += "R_GlobalParameter_Vec3 vec3_GParam = R_GlobalParameter_Vec3(gGlobalParam.m_AddressVec3);\n";

	code += "R_GlobalParameter_UVec2 uvec2_GParam = R_GlobalParameter_UVec2(gGlobalParam.m_AddressUVec2);\n";
	code += "R_GlobalParameter_UVec3 uvec3_GParam = R_GlobalParameter_UVec3(gGlobalParam.m_AddressUVec3);\n";
	code += "R_GlobalParameter_UVec4 uvec4_GParam = R_GlobalParameter_UVec4(gGlobalParam.m_AddressUVec4);\n";


	code += "S_ObMesh      Resource_ObMesh = ObMesh.m_Address[callSceneData.InstanceIndex];\n";

	code += "B_Indexs      mesh_uvIndex    = B_Indexs(Resource_ObMesh.m_AddressUVIndex);\n";
	code += "B_UV          mesh_uv         = B_UV(Resource_ObMesh.m_AddressUV);\n";
	code += "B_Faces       mesh_face       = B_Faces(Resource_ObMesh.m_AddressFaces);\n";

	//code += "S_FaceElement Element         = mesh_face.Element[callSceneData.PrimitiveIndex];\n";
	//code += "S_Material material           = m_Material[ Element.MaterialID ];\n";
	code += "S_Material material           = m_Material[ callSceneData.MaterialID ];\n";
	//code += "S_Material material           = m_Material[ 0 ];\n";
	return code;
}

static void f_着色器节点输出节点插座(C_节点基类* node) {
	auto* socket1 = new C_Vec3插座(L"颜色");
	auto* socket2 = new C_F32插座(L"粗糙");
	auto* socket3 = new C_F32插座(L"不透明");
	node->f_add插座(socket1, E_插座方向::e_插座Type_输入);
	node->f_add插座(socket2, E_插座方向::e_插座Type_输入);
	node->f_add插座(socket3, E_插座方向::e_插座Type_输入);

	DEF_Vec3插座数据(socket1) = {0.5f,0.5f,0.5f};
	DEF_F32插座数据(socket2) = 0.5;
	DEF_F32插座数据(socket3) = 1;
	//f_构建代码_分配渲染器GPU插座变量(*socket1);
	//f_构建代码_分配渲染器GPU插座变量(*socket2);
	//f_构建代码_分配渲染器GPU插座变量(*socket3);

}

static void f_着色器输出节点插座GPU参数绑定(std::vector<C_节点基类*>& outNodes) {
	for (auto& e : outNodes) {
		uint32 num = e->f_get输入插座Num();
		for (uint32 i = 1; i < num; ++i) {
			f_构建代码_分配渲染器GPU插座变量(*e->f_get输入插座(i));
		}
	}
}

static std::string f_着色器输出参数代码构建(std::vector<C_节点基类*>& outNodes, std::string& m_Code) {
	std::string shader_code;
	for (auto& e : outNodes) {
		auto* outSocket1 = e->f_get输入插座(1);
		auto* outSocket2 = e->f_get输入插座(2);
		auto* outSocket3 = e->f_get输入插座(3);
		shader_code += outSocket1->f_构建变量代码(0);
		shader_code += outSocket2->f_构建变量代码(0);
		shader_code += outSocket3->f_构建变量代码(0);

		shader_code += "callSceneData.Color = "     + outSocket1->f_getCode(0) + ";\n";
		shader_code += "callSceneData.roughness = " + outSocket2->f_getCode(0) + ";\n";
		shader_code += "callSceneData.alpha = "     + outSocket3->f_getCode(0) + ";\n";

		if (outSocket1->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(outSocket1->m_GPU缓存) = DEF_Vec3插座数据(outSocket1);
			f_buf_F32_at(outSocket2->m_GPU缓存) = DEF_F32插座数据(outSocket2);
			f_buf_F32_at(outSocket3->m_GPU缓存) = DEF_F32插座数据(outSocket3);
		}
	}
	return shader_code;
}


C_材质槽节点::C_材质槽节点(S_设备环境& ctx) : C_节点基类(DEF_材质槽节点, E_节点类型::e_节点Type_材质) {
	m_Name = L"材质";
	m_Ctx = ctx;
	
	C_插座基类* socket;
	DEF_创建UI32插座_I(L"数量");
	DEF_创建材质_1D插座_O(L"材质", ctx);

	DEF_UI32插座数据(f_get输入插座(1)) = 1;

	materials = (S_MaterialArray*)f_core_array_new(0, sizeof(S_材质*));

}

C_材质槽节点::~C_材质槽节点() {
	//auto* materials = DEF_材质插座_1D数据(f_get输出插座(1), 0);

	uint32 数量 = materials->count;
	for (uint32 i = 0; i < 数量; ++i) {
		S_材质* mat = f_array_at(S_材质*, materials, i);
		//S_材质* mat = *(S_材质**)f_core_array_back((S_Array*)materials);
		f_material_releasePBR(mat);
		//f_core_array_pop_back((S_Array*)materials);
	}
	f_core_array_free((S_Array*)materials);
}

bool C_材质槽节点::f_update() {
	uint32 num = DEF_UI32插座数据(f_get输入插座(1));
	//auto* materials = DEF_材质插座_1D数据(f_get输出插座(1), 0);

	uint32 原数量 = materials->count;

	if (原数量 > num) {
		for (uint32 i = num; i < 原数量; ++i) {
			//S_材质* mat = f_array_at(S_材质*, materials, i);
			S_材质* mat = *(S_材质**)f_core_array_back((S_Array*)materials);
			f_material_releasePBR(mat);
			f_core_array_pop_back((S_Array*)materials);
		}
	}
	else {
		for (uint32 i = 原数量; i < num; ++i) {
			S_材质* mat = f_material_createPBR();
			f_core_array_push_back((S_Array*)materials, (uint8*)&mat);
		}
	}

	f_get输出插座(1)->f_setData(materials);
	return false;
}

C_节点基类* f_node_创建材质槽节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_材质槽节点(ctx);
}

C_节点基类* f_node_加载材质槽节点(S_设备环境& ctx, FILE* f) {
	C_材质槽节点* node = new C_材质槽节点(ctx);
	return node;
}

void f_node_保存材质槽节点(C_节点基类* n, FILE* f) {
	C_材质槽节点* node = dynamic_cast<C_材质槽节点*>(n);
}




C_材质节点::C_材质节点(S_设备环境& ctx, C_节点树* link_tree) : C_节点基类(DEF_材质编辑节点, E_节点类型::e_节点Type_材质) {
	m_Name = L"材质编辑";
	m_Ctx = ctx;
	m_材质 = f_material_createPBR();

	C_插座基类* socket;
	DEF_创建材质_1D插座_I(L"材质");
	DEF_创建材质_1D插座_O(L"材质", ctx);

	m_材质节点树 = f_alloc_StrIndexProp(S_节点数据::g_材质节点树, L"");
	m_材质节点树.m_私有 = true;

	m_灯光标志位 = f_alloc_UI32FlagBitsProp(nullptr, L"灯光遮罩");
	m_灯光标志位.m_私有 = true;
	f_prop_UI32(m_灯光标志位) = 1;

	if (!link_tree) {
		link_tree = f_node_Create材质节点树(false, L"material_");

		auto* inNode = new C_输入组节点(ctx, 2);
		auto* outNode = new C_输出组节点(ctx);

		f_su_拷贝插座(this, outNode, E_插座方向::e_插座Type_输出, E_插座方向::e_插座Type_输入);
		socket = new C_着色器插座(L"着色器");
		outNode->f_add插座(socket, E_插座方向::e_插座Type_输入);


		inNode->f_add插座(new C_材质_1D插座(L"材质"), E_插座方向::e_插座Type_输出);

		//f_su_拷贝插座(this, inNode, E_插座方向::e_插座Type_输入, E_插座方向::e_插座Type_输出);
		inNode->m_插座可编辑 = true;
		link_tree->f_添加节点(inNode);
		link_tree->f_添加节点(outNode);
	}
	f_prop_MatPtr_切换ID(m_材质节点树, link_tree);


	C_节点基类::f_绑定子集节点树(link_tree);
	f_绑定this节点树(link_tree);
	link_tree->f_set父节点(this);

	f_get子集输入节点(m_InNodes);
	for (auto& e : m_InNodes) {
		e->f_set可添加删除插座起始位置(1);
	}

	m_函数指针 = nullptr;
}

C_材质节点::~C_材质节点() {
	f_material_releasePBR(m_材质);
}

void C_材质节点::f_get子集输入节点(std::vector<C_节点基类*>& inNodes) {
	inNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.push_back(e);
		}
	}
}

void C_材质节点::f_get子集输出节点(std::vector<C_节点基类*>& outNodes) {
	outNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			//outNodes.emplace_back(e);
			outNodes.push_back(e);
		}
	}
}

bool C_材质节点::f_update() {
	auto* materials = DEF_材质插座_1D数据(f_get输入插座(1), 0);
	f_get输出插座(1)->f_setData(materials);
	//auto* materials = DEF_材质插座_1D数据(f_get输出插座(1), 0);

	if (f_get输入插座(1)->f_isLink() == false) {
		f_core_array_resize((S_Array*)materials, 1);
		materials->ptr_userData[0] = m_材质;
	}


	

	if (!m_子集节点树->m_程序集 || m_子集节点树->m_节点结构改变) {
		if (!m_子集节点树->m_开始编译) {
			m_函数指针 = nullptr;
			m_子集节点树->f_准备编译节点树();

			m_子集节点树->m_开始编译 = true;
			f_NodeCtx_物理模拟线程入栈(this);
		}
		return true;
	}
	else if (m_子集节点树->m_程序集 && !m_函数指针) {
		std::string 函数名称 = f_WStringToString(m_子集节点树->m_IDName);
		E_JIT方式 方式 = (E_JIT方式)f_prop_enum(m_子集节点树->m_编译方式);
		m_函数指针 = (expand_接口函数_材质节点)f_JIT_取函数指针(m_子集节点树->m_程序集, 函数名称, 方式);
	}



	if (m_函数指针) {
		std::vector<void*> inData;
		uint32 inNum = f_get输入插座Num();
		uint32 outNum = f_get输出插座Num();

		for (uint32 i = 0; i < inNum; ++i) {
			inData.push_back(f_get输入插座(i)->f_getData(0));
		}
		for (uint32 i = 0; i < outNum; ++i) {
			inData.push_back(f_get输出插座(i)->f_getData(0));
		}

		f_get子集输出节点(m_OutNudes);


		//f_NT_刷新全局参数(m_子集节点树);

		S_Scene* scene = f_NodeCtx_get默认场景();
		S_Material* GPU材质 = f_buf_map板载缓存<S_Material>(S_光追后端::m_材质);
		S_着色* shader = DEF_着色器数据(m_OutNudes[0]->f_get输入插座(2), 0);

		//void** jit参数 = m_子集节点树->m_节点JIT参数.data();
		//void** jit参数 = m_子集节点树->m_JIT二级参数.data();
		for (uint32 i = 0; i < materials->count; ++i) {
			uint32 全局光照材质Offset = materials->ptr_userData[i]->m_光追材质ID;
			
			GPU材质[全局光照材质Offset].m_shaderIndex = shader->m_ShaderIndex;
			GPU材质[全局光照材质Offset].m_LigthMask = f_prop_UI32(m_灯光标志位);
			
			GPU材质[全局光照材质Offset].m_colorTex = -1;
			GPU材质[全局光照材质Offset].m_emissionTex = -1;
			GPU材质[全局光照材质Offset].m_reflectTex = -1;
			GPU材质[全局光照材质Offset].m_refractTex = -1;
			GPU材质[全局光照材质Offset].m_roughnessTex = -1;
			GPU材质[全局光照材质Offset].m_alphaTex = -1;
			
			
			bool r = m_函数指针(GPU材质[全局光照材质Offset], i, inData.data(), C_节点树::g_节点JIT参数.data());
			//bool r = m_函数指针(GPU材质[全局光照材质Offset], inData.data(), nullptr);
		}

		f_buf_unmap板载缓存(S_光追后端::m_材质);

		materials->ptr_userData[0]->m_Shader = shader;
	}
	else {
		materials->ptr_userData[0]->m_Shader = nullptr;
	}

	
	return false;
}

void C_材质节点::f_异步解算() {
	std::string 材质函数名称 = f_WStringToString(m_子集节点树->m_IDName);
	E_JIT方式 方式 = (E_JIT方式)f_prop_enum(m_子集节点树->m_编译方式);

	m_函数指针 = nullptr;
	m_编译成功 = true;
	

	std::string path = f_file_get路径(S_节点数据::g_工程文件材质节点代码绝对路径) + 材质函数名称 + ".cpp";
	bool 编译成功 = f_NT_编译节点(this, path, true);


	switch (方式) {
	case E_JIT方式::e_jit_llvm: path = f_file_get路径(S_节点数据::g_工程文件材质节点代码绝对路径) + 材质函数名称 + ".bc"; break;
	case E_JIT方式::e_jit_dll: path = f_file_get路径(S_节点数据::g_工程文件材质节点代码绝对路径) + 材质函数名称 + ".ex"; break;
	}


	
	if (编译成功 && f_file_文件是否存在(path)) {
		m_子集节点树->m_程序集 = f_JIT_加载代码(path, 方式);

		m_函数指针 = (expand_接口函数_材质节点)f_NT_初始化函数接口(m_子集节点树->m_程序集, 材质函数名称, 方式);
		if (!m_函数指针) {
			goto To_重新编译;
			
		}
		m_子集节点树->m_节点结构改变 = false;
		m_子集节点树->m_开始编译 = false;
		return;
	}
	else {
	To_重新编译:
		f_node_销毁程序集(m_子集节点树);
		m_编译成功 = false;
		//m_函数指针 = (expand_接口函数_材质节点)f_JIT_取函数指针(m_子集节点树->m_程序集, 材质函数名称, 方式);
	}

	f_set是否要更新(true);
}

std::string C_材质节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	//std::string name = f_WStringToString(f_prop_Str(m_子集节点树->m_函数名称));
	std::string name = f_WStringToString(m_子集节点树->m_IDName);
	uint32 inNum = f_get输入插座Num();
	uint32 outNum = f_get输出插座Num();



	bool 内联调用 = f_NT_是否内联调用(this);
	bool 编译 = true;
	if (内联调用) {
		name += "_inline";

		if (m_子集节点树->m_以编译 & E_节点树编译位标志::e_节点编译_内联调用) {
			编译 = false;
		}
	}
	else {
		if (m_子集节点树->m_以编译 & E_节点树编译位标志::e_节点编译_外部调用) {
			编译 = false;
		}
	}


	
	if (编译) {
		if (内联调用) {
			m_子集节点树->m_以编译 |= E_节点树编译位标志::e_节点编译_内联调用;

		}
		else {
			m_子集节点树->m_以编译 |= E_节点树编译位标志::e_节点编译_外部调用;

		}

		m_子集节点树->m_以编译 = E_节点树编译位标志::e_节点编译_完成;

		//std::string 函数声明 = "// ======== " + name + " ========\n";
		std::string 函数声明 = " bool " + name + "(" + DEF_S(S_Material) + "& self, int32 " + f_代码构建_ID变量名称(this) + ", void** inData, " + DEF_S(DEF_编译可调参数) + ")";


		声明 += "static " DEF_S(DEF_编译全局可调参数) " = nullptr;\n";

		声明 += "// ======== " + name + " ========\n";

		std::string extern_declspec = "extern \"C\" { __declspec(dllexport) ";
		if (extern_declspec.size()) {
			声明 += extern_declspec + 函数声明 + ";}\n";
		}
		else {
			声明 += 函数声明 + ";\n";
		}




		std::string 函数定义 = 函数声明;
		函数定义 += "{\n";

		f_get子集输入节点(m_InNodes);
		f_get子集输入节点(m_OutNudes);
		f_代码构建_输入输出节点参数(this, m_InNodes, {});


		函数定义 += DEF_S(DEF_编译全局可调参数赋值)";\n";
		函数定义 += "S_Material* " + g材质_参数 + " = &self;\n";

		函数定义 += f_NT_编译节点树(m_子集节点树, 定义, 声明);


		函数定义 += "return true;\n";
		函数定义 += "}\n";
		定义.push_back(函数定义);
	}


	//if (m_子集节点树->m_以编译 != E_节点树编译位标志::e_节点编译_完成) {
	//}
	//else {
	//}


	if (内联调用) {
		m_Code += "{\n";
		for (uint32 i = 0; i < inNum; ++i) {
			m_Code += f_get输入插座(i)->f_构建变量代码(0);
		}
		for (uint32 i = 0; i < outNum; ++i) {
			m_Code += f_get输出插座(i)->f_构建变量代码(0);
		}

		//函数调用代码
		m_Code += name + "(";
		for (uint32 i = 1; i < inNum; ++i) {
			m_Code += f_get输入插座(i)->f_getCode(0);
			if (i < outNum - 2) {
				m_Code += ", ";
			}
		}
		for (uint32 i = 1; i < outNum; ++i) {
			m_Code += ", " + f_get输出插座(i)->f_getCode(0);

		}
		m_Code += ");\n";
		m_Code += "}\n";
	}


	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode += m_ReleaseCode;
		return "";
	}
	释放 += m_ReleaseCode;
	return m_Code;
}

void C_材质节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	if (S_引擎::读取加载文件版本号 <= S_节点数据::g_低版本号_6) {
		f_prop_Load(m_灯光标志位, f);
	}
	else {
		S_文件块 文件块 = f_file_读取文件块(f);
		if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
			const uint8* 下一次读取数据指针 = 文件块.m_data;

			if (f_file_版本对比(文件块, S_节点数据::g_低版本号_6, S_节点数据::g_文件版本号)) {
				f_prop_Load(m_灯光标志位, 下一次读取数据指针);
			}
		}
		free(文件块.m_data);
	}
}

void C_材质节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_灯光标志位, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建材质节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_材质节点(ctx, 子节点树);
}

C_节点基类* f_node_加载材质节点(S_设备环境& ctx, FILE* f) {
	std::wstring 链接的节点树名称 = f_file_读取字符串(f);

	if (S_节点数据::G用于重新映射节点树到节点的容器.find(链接的节点树名称) == S_节点数据::G用于重新映射节点树到节点的容器.end()) {
		f_node_加载节点树(ctx, f);
	}

	C_材质节点* node = new C_材质节点(ctx, S_节点数据::G用于重新映射节点树到节点的容器[链接的节点树名称]);
	return node;
}

void f_node_保存材质节点(C_节点基类* n, FILE* f) {
	C_材质节点* node = dynamic_cast<C_材质节点*>(n);

	auto* tree = node->f_get子集树();
	f_file_保存字符串(f, tree->m_IDName);

	if (tree->m_未保存或加载) {
		tree->m_未保存或加载 = false;

		std::vector<C_节点树*> trees = { tree };
		f_node_保存节点树(trees, f);
	}
}




C_当前材质节点::C_当前材质节点(S_设备环境& ctx) : C_节点基类(DEF_当前材质节点, E_节点类型::e_节点Type_材质) {
	m_Name = L"当前材质";
	m_Ctx = ctx;

	C_插座基类* socket;
	//DEF_创建材质插座_I(L"材质");
	DEF_创建材质插座_O(L"材质", ctx);

}

C_当前材质节点::~C_当前材质节点() {
}

bool C_当前材质节点::f_update() {
	return false;
}

std::string C_当前材质节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	auto name = "(&self)";

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_当前材质节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		//if (f_file_版本对比(文件块, S_节点数据::g_低版本号_6, S_节点数据::g_文件版本号)) {
		//}
	}
	free(文件块.m_data);
}

void C_当前材质节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建当前材质节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_当前材质节点(ctx);
}

C_节点基类* f_node_加载当前材质节点(S_设备环境& ctx, FILE* f) {
	C_当前材质节点* node = new C_当前材质节点(ctx);
	return node;
}

void f_node_保存当前材质节点(C_节点基类* n, FILE* f) {
	C_当前材质节点* node = dynamic_cast<C_当前材质节点*>(n);
}





C_着色器节点::C_着色器节点(S_设备环境& ctx, C_节点树* link_tree) : C_节点基类(DEF_着色器节点, E_节点类型::e_节点Type_材质) {
	m_Name = L"着色器";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建着色器插座_O(L"着色器");


	m_外部加载 = f_alloc_BoolProp(nullptr, L"外部加载");
	m_外部加载.m_私有 = true;
	f_prop_Bool(m_外部加载) = false;

	m_着色阶段 = f_alloc_EnumProp(nullptr, { {L"光追回调", ""}, {L"顶点", ""}, {L"几何", ""}, {L"片源", ""}, {L"计算", ""}}, L"函数名称");
	m_着色阶段.m_私有 = true;
	
	m_节点树 = f_alloc_StrIndexProp(S_节点数据::g_着色节点树, L"");
	m_节点树.m_私有 = true;

	m_源码类型 = f_alloc_EnumProp(nullptr, { {L"spv", ""}, {L"glsl", ""} }, L"着色文件类型");
	m_源码类型.m_私有 = true;


	if (!link_tree) {
		link_tree = f_node_Create着色节点树(false, L"着色");

		auto* inNode = new C_输入组节点(ctx);
		auto* outNode = new C_输出组节点(ctx);

		f_su_拷贝插座(this, inNode, E_插座方向::e_插座Type_输入, E_插座方向::e_插座Type_输出);
		//f_su_拷贝插座(this, outNode, E_插座方向::e_插座Type_输出, E_插座方向::e_插座Type_输入);
		f_着色器节点输出节点插座(outNode);


		inNode->m_插座可编辑 = true;
		link_tree->f_添加节点(inNode);
		link_tree->f_添加节点(outNode);

	}
	f_prop_MatPtr_切换ID(m_节点树, link_tree);

	C_节点基类::f_绑定子集节点树(link_tree);
	f_绑定this节点树(m_当前节点所在节点树);


	std::vector<C_节点基类*> outNodes;
	f_get子集输出节点(outNodes);
	f_着色器输出节点插座GPU参数绑定(outNodes);
}

C_着色器节点::~C_着色器节点() {
}

void C_着色器节点::f_get子集输入节点(std::vector<C_节点基类*>& inNodes) {
	inNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.emplace_back(e);
		}
	}
}

void C_着色器节点::f_get子集输出节点(std::vector<C_节点基类*>& outNodes) {
	outNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			outNodes.emplace_back(e);
		}
	}
}

bool C_着色器节点::f_update() {
	S_着色* shader = DEF_着色器数据(f_get输出插座(1), 0);
	shader->m_ShaderIndex = m_子集节点树->m_ID;

	return false;
}

std::string C_着色器节点::DEF_节点编译函数{
	std::string extern_declspec;
	
	//#pragma omp parallel
	{
		//#pragma omp parallel
		{
			m_Code = "";
			m_ReleaseCode = "";

			uint32 inNum = f_get输入插座Num();
			for (uint32 i = 0; i < inNum; ++i) {
				m_Code += f_get输入插座(i)->f_构建变量代码(0);
			}


			m_子集节点树->m_Code = m_Code;
			m_子集节点树->m_ReleaseCode = m_ReleaseCode;
			std::cout << "线程2 : " << std::endl;
		}


		//#pragma omp parallel
		{
			if (m_子集节点树->m_以编译) {

			}
			else {
				m_子集节点树->m_以编译 = 1;
				int32 err = -1;

				if (f_prop_Bool(m_子集节点树->m_外部加载) == false) {
				//着色器代码生成
					std::string shader_code;
					shader_code += "#version 460 core\n";
					shader_code += "#extension GL_EXT_ray_tracing : require\n";
					shader_code += "#extension GL_EXT_scalar_block_layout : enable\n";
					shader_code += "#extension GL_EXT_buffer_reference2 : require\n";
					shader_code += "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
					shader_code += "#extension GL_GOOGLE_include_directive : enable\n";


					shader_code += "#include \"./shader_std.h\"\n";
					shader_code += "#include \"./shader_rcall.h\"\n";
					shader_code += "#include \"./shader_built_in_functions.h\"\n";
					shader_code += "#include \"./shader_PBR.h\"\n";
					shader_code += "#include \"./shader_rcall.h\"\n";
					shader_code += "#include \"./shader_ob.h\"\n";
					shader_code += "#include \"./shader_texture.h\"\n";


					std::vector<std::string> 函数定义;
					std::string 函数变量声明;
					std::string 实现代码 = f_NT_编译节点树(m_子集节点树, 函数定义, 函数变量声明);


					shader_code += 函数变量声明;
					for (auto& e : 函数定义) {
						shader_code += e;
					}

					shader_code += "void main() {\n";
					shader_code += f_着色器引用数据声明();
					shader_code += 实现代码;

					std::vector<C_节点基类*> outNodes;
					f_get子集输出节点(outNodes);
					shader_code += f_着色器输出参数代码构建(outNodes, m_Code);

					shader_code += "}\n";


					//auto path = S_节点数据::g_工程文件着色节点代码路径;
					auto path = f_WStringToString(f_prop_Str(m_子集节点树->m_代码文件路径));
					auto name = f_file_取无后缀文件名(path);
					if (name == ".") {
						//name = f_WStringToString(f_prop_Str(m_子集节点树->m_函数名称));
						//f_prop_Str(m_子集节点树->m_代码文件路径) += f_prop_Str(m_子集节点树->m_函数名称) + L".spv";
						name = f_WStringToString(m_子集节点树->m_IDName);
						f_prop_Str(m_子集节点树->m_代码文件路径) += m_子集节点树->m_IDName + L".spv";
					}
					auto 着色文件路径 = S_引擎::g_工程文件临时路径 + name + ".rcall";
					FILE* f = fopen(着色文件路径.c_str(), "w");
					if (f) {
						f_file_保存文本(f, shader_code);
						fclose(f);
					}


					std::string cmd = S_引擎::m_着色器编译器路径;
					cmd += " -V " + 着色文件路径;
					cmd += " -o " + path;
					cmd += " -I" + S_引擎::m_着色器头文件路径;
					cmd += " --target-env vulkan1.3";

					err = system(cmd.c_str());
					//f_bd_GLSLtoSPV(E_着色阶段::e_光追回调, shader_code, "d:/call_shader.spv");
					std::cout << "线程1 : " << err << std::endl;
				}


				if (!err) {
					std::string path = f_WStringToString(f_prop_Str(m_子集节点树->m_代码文件路径));
					f_bd_安装光追材质着色器(f_NodeCtx_get默认场景()->m_光追后端, m_子集节点树->m_ID, path, m_子集节点树->m_ID);
					std::cout << "编译着色器" << std::endl;
				}

			}


		}

	}

	S_着色* shader = DEF_着色器数据(f_get输出插座(1), 0);
	shader->m_ShaderIndex = m_子集节点树->m_ID;



	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}

	释放 += m_ReleaseCode;
	return m_Code;

}

void C_着色器节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_着色器节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_创建着色器节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_着色器节点(ctx, 子节点树);
}

C_节点基类* f_node_加载着色器节点(S_设备环境& ctx, FILE* f) {
	std::wstring 链接的节点树名称 = f_file_读取字符串(f);

	if (S_节点数据::G用于重新映射节点树到节点的容器.find(链接的节点树名称) == S_节点数据::G用于重新映射节点树到节点的容器.end()) {
		f_node_加载节点树(ctx, f);
	}

	C_着色器节点* node = new C_着色器节点(ctx, S_节点数据::G用于重新映射节点树到节点的容器[链接的节点树名称]);
	return node;
}

void f_node_保存着色器节点(C_节点基类* n, FILE* f) {
	C_着色器节点* node = dynamic_cast<C_着色器节点*>(n);

	auto* tree = node->f_get子集树();
	f_file_保存字符串(f, tree->m_IDName);

	if (tree->m_未保存或加载) {
		tree->m_未保存或加载 = false;

		std::vector<C_节点树*> trees = { tree };
		f_node_保存节点树(trees, f);
	}
}



C_自发光材质节点::C_自发光材质节点(S_设备环境& ctx) : C_节点基类(DEF_自发光材质节点, E_节点类型::e_节点Type_材质) {
	m_Name = L"自发光材质";
	m_Ctx = ctx;

	C_插座基类* socket;


}

C_自发光材质节点::~C_自发光材质节点() {
}

bool C_自发光材质节点::f_update() {
	return false;
}

void C_自发光材质节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_自发光材质节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_加载自发光材质节点(S_设备环境& ctx, FILE* f) {
	C_自发光材质节点* node = new C_自发光材质节点(ctx);
	return node;
}

void f_node_保存自发光材质节点(C_节点基类* n, FILE* f) {
	C_自发光材质节点* node = dynamic_cast<C_自发光材质节点*>(n);
}








C_设置物体材质节点::C_设置物体材质节点(S_设备环境& ctx) : C_节点基类(DEF_设置网格材质节点, E_节点类型::e_节点Type_材质) {
	m_Name = L"设置物体材质";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建材质_1D插座_I(L"材质", ctx);
	DEF_创建UI32插座_I(L"槽", ctx);
	DEF_创建网格_1D插座_I(L"网格", ctx);

	f_get输入插座(3)->f_set多输入();

	
	DEF_创建材质_1D插座_O(L"物体", ctx);
}

C_设置物体材质节点::~C_设置物体材质节点() {
}

bool C_设置物体材质节点::f_update() {
	auto* mats = DEF_材质插座_1D数据(f_get输入插座(1), 0);
	uint32 mat_num = mats->count;
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);

	
	uint32 组数量 = socket3->f_getLinkNum();

	if (!mat_num) {
		for (uint32 j = 0; j < 组数量; ++j) {
			auto& mes = *DEF_网格插座_1D数据(socket3, j);
			auto* me_ptr = mes.ptr_userData;
			uint32 num = mes.count;

			if (mat_num >= num) {
				for (uint32 i = 0; i < num; ++i) {
					uint32 面数量 = me_ptr[i]->m_面->m_Mem.m_大小;
					if(!面数量) continue;

					S_FaceElement* fe = f_buf_面元素_ptr(*me_ptr[i]->m_面);
					for (uint32 f = 0; f < 面数量; ++f) {
						fe[f].FacesMooth = 1;
						fe[f].MaterialID = 0;
					}
				}
			}
			else {
				for (uint32 i = 0; i < num; ++i) {
					uint32 面数量 = me_ptr[i]->m_面->m_Mem.m_大小;
					if (!面数量) continue;

					S_FaceElement* fe = f_buf_面元素_ptr(*me_ptr[i]->m_面);
					for (uint32 f = 0; f < 面数量; ++f) {
						fe[f].FacesMooth = 1;
						fe[f].MaterialID = 0;
					}
				}
			}
		}

		f_get输出插座(1)->f_setData((S_MaterialArray*)nullptr);
		return false;
	}

	auto* mat_ptr = mats->ptr_userData;
	
	
	uint32 槽 = DEF_UI32插座数据(socket2);

	for (uint32 j = 0; j < 组数量; ++j) {
		auto& mes = *DEF_网格插座_1D数据(socket3, j);
		auto* me_ptr = mes.ptr_userData;
		uint32 num = mes.count;



		for (uint32 i = 0; i < num; ++i) {
			uint32 面数量 = me_ptr[i]->m_面->m_Mem.m_大小;
			if (!面数量) continue;

			auto* 材质槽ID = me_ptr[i]->m_材质槽ID->ptr_userData;
			bool 槽单例 = me_ptr[i]->m_材质槽ID->count >= 面数量;

			S_FaceElement* fe = f_buf_面元素_ptr(*me_ptr[i]->m_面);
			uint32 材质ID;

			if (mat_num >= num) {
				材质ID = mat_ptr[i]->m_光追材质ID;
			}
			else {
				材质ID = mat_ptr[0]->m_光追材质ID;
			}
			

			for (uint32 f = 0; f < 面数量; ++f) {
				fe[f].FacesMooth = 1;
				
				if(槽单例) {
					if (材质槽ID[f] == 槽) fe[f].MaterialID = 材质ID;
				}
				else {
					if (材质槽ID[0] == 槽) 
						fe[f].MaterialID = 材质ID;
				}
				//if (材质槽ID[f] == 槽) {
				//	face[f].MaterialID = 材质ID;
				//}
				//face[f].MaterialID = 0;
				//face[f].ShaderType = 0;
			}
		}

		//if (mat_num >= num) {
		//	
		//}
		//else {
		//	for (uint32 i = 0; i < num; ++i) {
		//		if(!me_ptr[i]->m_面->m_Size) continue;
		//
		//		auto* 材质槽ID = me_ptr[i]->m_材质槽ID.data();
		//		S_FaceElement* face = f_buf_map板载缓存<S_FaceElement>(me_ptr[i]->m_面);
		//		//uint64 mat_address = f_vk_getBufAddress(mat_ptr[0]->m_光追材质);
		//		uint32 材质ID = mat_ptr[0]->m_光追材质ID;
		//		for (uint32 f = 0; f < me_ptr[i]->m_面->m_Size; ++f) {
		//			face[f].FacesMooth = 1;
		//			face[f].MaterialID = 材质ID;
		//			//face[f].ShaderType = 0;
		//			//assert(face[f].MaterialID <= 2 && face[f].MaterialID >= 0);
		//			if (材质槽ID[f]) {
		//
		//			}
		//		}
		//
		//		f_buf_unmap板载缓存(me_ptr[i]->m_面);
		//	}
		//}
	}

	f_get输出插座(1)->f_setData(mats);
	return false;
}

void C_设置物体材质节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_设置物体材质节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_创建设置物体材质节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_设置物体材质节点(ctx);
}

C_节点基类* f_node_加载设置物体材质节点(S_设备环境& ctx, FILE* f) {
	C_设置物体材质节点* node = new C_设置物体材质节点(ctx);
	return node;
}

void f_node_保存设置物体材质节点(C_节点基类* n, FILE* f) {
	C_设置物体材质节点* node = dynamic_cast<C_设置物体材质节点*>(n);
}






C_PBR材着色器节点::C_PBR材着色器节点(S_设备环境& ctx, C_节点树* link_tree) : C_节点基类(DEF_PBR着色器节点, E_节点类型::e_节点Type_着色器) {
	m_Name = L"着色器";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建纹理插座_I(L"颜色", ctx);
	DEF_创建纹理插座_I(L"发光", ctx);
	DEF_创建纹理插座_I(L"反射", ctx);
	DEF_创建纹理插座_I(L"折射", ctx);
	DEF_创建纹理插座_I(L"粗糙", ctx);
	DEF_创建纹理插座_I(L"透明", ctx);
	DEF_创建纹理插座_I(L"法线", ctx);

	DEF_创建F32插座_I(L"透射", nullptr);
	DEF_创建F32插座_I(L"各向限异性", nullptr);
	DEF_创建F32插座_I(L"溢色", nullptr);
	

	DEF_纹理插座数据(f_get输入插座(1), 0)->m_格式 = E_纹理格式::e_tf_RGB32;
	DEF_纹理插座数据(f_get输入插座(2), 0)->m_格式 = E_纹理格式::e_tf_RGB32;
	DEF_纹理插座数据(f_get输入插座(3), 0)->m_格式 = E_纹理格式::e_tf_R32;
	DEF_纹理插座数据(f_get输入插座(4), 0)->m_格式 = E_纹理格式::e_tf_R32;
	DEF_纹理插座数据(f_get输入插座(5), 0)->m_格式 = E_纹理格式::e_tf_R32;
	DEF_纹理插座数据(f_get输入插座(6), 0)->m_格式 = E_纹理格式::e_tf_R32;
	DEF_纹理插座数据(f_get输入插座(7), 0)->m_格式 = E_纹理格式::e_tf_RGB32;
	DEF_纹理插座数据(f_get输入插座(3), 0)->m_默认颜色 = {0,0,0};

	DEF_创建着色器插座_O(L"着色器");


	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(1));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(2));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(3));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(4));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(5));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(6));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(7));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(8));



	m_节点树 = f_alloc_StrIndexProp(S_节点数据::g_着色节点树, L"着色");
	m_节点树.m_私有 = true;

	if (!link_tree) {
		link_tree = f_node_Create着色节点树(false, L"着色");

		auto* inNode = new C_输入组节点(ctx);
		auto* outNode = new C_输出组节点(ctx);

		socket = new C_Vec3插座(L"颜色"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		socket = new C_Vec3插座(L"发光"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		socket = new C_F32插座(L"反射"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		socket = new C_F32插座(L"折射"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		socket = new C_F32插座(L"粗糙"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		socket = new C_F32插座(L"透明"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		socket = new C_Vec3插座(L"法线"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		socket = new C_F32插座(L"透射"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		socket = new C_F32插座(L"各向限异性"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		socket = new C_F32插座(L"溢色"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
		
		//outNode->f_add插座(new C_Vec4插座(L"颜色"), E_插座方向::e_插座Type_输入);
		f_着色器节点输出节点插座(outNode);
		
		link_tree->f_添加节点(inNode);
		link_tree->f_添加节点(outNode);

		//outNode->m_插座可编辑 = false;
		f_prop_Bool(link_tree->m_外部加载) = false;
		//f_prop_Str(link_tree->m_代码文件路径) += L"PBR_光线回调.spv";
	}
	f_prop_MatPtr_切换ID(m_节点树, link_tree);

	f_绑定子集节点树(link_tree);
	f_绑定this节点树(link_tree);

	std::vector<C_节点基类*> outNodes;
	f_get子集输出节点(outNodes);
	f_着色器输出节点插座GPU参数绑定(outNodes);
}

C_PBR材着色器节点::~C_PBR材着色器节点() {
}

void C_PBR材着色器节点::f_get子集输入节点(std::vector<C_节点基类*>& inNodes) {
	inNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.emplace_back(e);
		}
	}
}

void C_PBR材着色器节点::f_get子集输出节点(std::vector<C_节点基类*>& outNodes) {
	outNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			outNodes.emplace_back(e);
		}
	}
}

bool C_PBR材着色器节点::f_update() {
	//auto* materials = DEF_材质插座_1D数据(f_get输入插座(1), 0);

	/*auto& 颜色 = *DEF_纹理插座数据(f_get输入插座(1), 0);
	auto& 发光 = *DEF_纹理插座数据(f_get输入插座(2), 0);
	auto& 反射 = *DEF_纹理插座数据(f_get输入插座(3), 0);
	auto& 折射 = *DEF_纹理插座数据(f_get输入插座(4), 0);
	auto& 粗糙 = *DEF_纹理插座数据(f_get输入插座(5), 0);
	auto& 透明 = *DEF_纹理插座数据(f_get输入插座(6), 0);
	auto& 法线 = *DEF_纹理插座数据(f_get输入插座(7), 0);*/
	

	
	S_光追后端::f_重置渲染帧记录();
	return false;
}

std::string C_PBR材着色器节点::DEF_节点编译函数{
	std::string extern_declspec;
	if (f_NT_是否内联调用(this)) {

	}

	S_着色* shader = DEF_着色器数据(f_get输出插座(1), 0);
	shader->m_ShaderIndex = m_子集节点树->m_ID;


	//#pragma omp parallel
	{
		//#pragma omp parallel
		{
			m_Code = "";
			m_ReleaseCode = "";


			uint32 inNum = f_get输入插座Num();
			for (uint32 i = 0; i < inNum; ++i) {
				m_Code += f_get输入插座(i)->f_构建变量代码(0);
			}


			auto socket1 = f_get输入插座(1);
			S_纹理* tex = DEF_纹理插座数据(socket1, 0);
			if (socket1->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket1->f_isLink()))
				//m_Code += "(*(vec3*)&(" + g材质_参数 + "->m_color_r)) = " + socket1->f_getCode() + ";\n";
			    m_Code += g材质_参数 + "->m_color = " + socket1->f_getCode(0) + ";\n";
			else
				m_Code += g材质_参数 + "->m_colorTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket1->f_getCode(0) + ");\n";


			auto socket2 = f_get输入插座(2);
			tex = DEF_纹理插座数据(socket2, 0);
			if (socket2->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket2->f_isLink()))
				//m_Code += "(*(vec3*)&(" + g材质_参数 + "->m_emission_r)) = " + socket2->f_getCode() + ";\n";
				m_Code += g材质_参数 + "->m_emission = " + socket2->f_getCode(0) + ";\n";
			else
				m_Code += g材质_参数 + "->m_emissionTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket2->f_getCode(0) + ");\n";


			auto socket3 = f_get输入插座(3);
			tex = DEF_纹理插座数据(socket3, 0);
			if (socket3->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket3->f_isLink()))
				m_Code += g材质_参数 + "->m_reflect = " + socket3->f_getCode(0) + ".x;\n";
			else
				m_Code += g材质_参数 + "->m_reflectTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket3->f_getCode(0) + ");\n";


			auto socket4 = f_get输入插座(4);
			tex = DEF_纹理插座数据(socket4, 0);
			if (socket4->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket4->f_isLink()))
				m_Code += g材质_参数 + "->m_refract = " + socket4->f_getCode(0) + ".x;\n";
			else
				m_Code += g材质_参数 + "->m_refractTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket4->f_getCode(0) + ");\n";


			auto socket5 = f_get输入插座(5);
			tex = DEF_纹理插座数据(socket5, 0);
			if (socket5->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket5->f_isLink()))
				m_Code += g材质_参数 + "->m_roughness = " + socket5->f_getCode(0) + ".x;\n";
			else
				m_Code += g材质_参数 + "->m_roughnessTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket5->f_getCode(0) + ");\n";


			auto socket6 = f_get输入插座(6);
			tex = DEF_纹理插座数据(socket6, 0);
			if (socket6->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket6->f_isLink()))
				m_Code += g材质_参数 + "->m_alpha = " + socket6->f_getCode(0) + ".x;\n";
			else
				m_Code += g材质_参数 + "->m_alphaTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket6->f_getCode(0) + ");\n";


			auto socket7 = f_get输入插座(7);
			if (socket7->f_isLink()) m_Code += g材质_参数 + "->m_normalTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + f_get输入插座(7)->f_getCode(0) + ");\n";

			auto socket8 = f_get输入插座(8);
			m_Code += g材质_参数 + "->m_transmission = " + f_get输入插座(8)->f_getCode(0) + ";\n";

			auto socket9 = f_get输入插座(9);
			m_Code += g材质_参数 + "->m_anisotropy = " + f_get输入插座(9)->f_getCode(0) + ";\n";


			m_子集节点树->m_Code = m_Code;
			m_子集节点树->m_ReleaseCode = m_ReleaseCode;
			//std::cout << "线程2 : " << std::endl;

			//================= 着色器输入变量 ==========================
			std::vector<C_节点基类*> inNodes;
			f_get子集输入节点(inNodes);

			for (auto& e : inNodes) {
				
				auto* outSocket1 = e->f_get输出插座(1);
				if (socket1->f_isLink()) {
					outSocket1->f_setCode("material.m_colorTex");
				}
				else {
					outSocket1->f_setCode("material.m_color");
				}
				
				auto* outSocket2 = e->f_get输出插座(2);
				if (socket2->f_isLink()) {
					outSocket2->f_setCode("material.m_emissionTex");
				}
				else {
					outSocket2->f_setCode("material.m_emission");
				}

				auto* outSocket3 = e->f_get输出插座(3);
				if (socket3->f_isLink()) {
					outSocket3->f_setCode("material.m_reflectTex");
				}
				else {
					outSocket3->f_setCode("material.m_reflect");
				}

				auto* outSocket4 = e->f_get输出插座(4);
				if (socket4->f_isLink()) {
					outSocket4->f_setCode("material.m_refractTex");
				}
				else {
					outSocket4->f_setCode("material.m_reflect");
				}

				auto* outSocket5 = e->f_get输出插座(5);
				if (socket5->f_isLink()) {
					outSocket5->f_setCode("material.m_roughnessTex");
				}
				else {
					outSocket5->f_setCode("material.m_roughness");
				}

				auto* outSocket6 = e->f_get输出插座(6);
				if (socket6->f_isLink()) {
					outSocket6->f_setCode("material.m_alphaTex");
				}
				else {
					outSocket6->f_setCode("material.m_alpha");
				}

				auto* outSocket7 = e->f_get输出插座(7);
				if (socket7->f_isLink()) {
					outSocket7->f_setCode("material.m_normalTex");
				}

				auto* outSocket8 = e->f_get输出插座(8);
				outSocket8->f_setCode("material.m_transmission");
			}
			
		}


		//#pragma omp parallel
		{
			bool 内联调用 = f_NT_是否内联调用(this);
			bool 编译 = true;
			if (内联调用) {
				if (m_子集节点树->m_以编译 & E_节点树编译位标志::e_节点编译_内联调用) {
					编译 = false;
				}
			}
			else {
				if (m_子集节点树->m_以编译 & E_节点树编译位标志::e_节点编译_外部调用) {
					编译 = false;
				}
			}

			if (编译) {
				m_子集节点树->m_以编译 |= E_节点树编译位标志::e_节点编译_内联调用;
				int32 err = 0;
				//auto name = f_WStringToString(f_prop_Str(m_子集节点树->m_函数名称));
				auto name = f_WStringToString(m_子集节点树->m_IDName);
				auto 着色文件路径 = S_节点数据::g_工程文件着色节点代码绝对路径 + name + ".rcall";
				auto SPV = S_节点数据::g_工程文件着色节点代码绝对路径 + name + ".spv";

				if (f_prop_Bool(m_子集节点树->m_外部加载) == false) {
					//着色器代码生成
					std::string shader_code;
					shader_code += "#version 460 core\n";
					shader_code += "#extension GL_EXT_ray_tracing : require\n";
					shader_code += "#extension GL_EXT_scalar_block_layout : enable\n";
					shader_code += "#extension GL_EXT_nonuniform_qualifier : enable\n";
					shader_code += "#extension GL_EXT_buffer_reference2 : require\n";
					shader_code += "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
					shader_code += "#extension GL_GOOGLE_include_directive : enable\n";


					shader_code += "#include \"./shader_std.h\"\n";
					shader_code += "#include \"./shader_built_in_functions.h\"\n";
					shader_code += "#include \"./shader_PBR.h\"\n";
					shader_code += "#include \"./shader_rcall.h\"\n";
					shader_code += "#include \"./shader_ob.h\"\n";
					shader_code += "#include \"./shader_texture.h\"\n";
					shader_code += "#include \"./shader_sample.h\"\n";



					std::vector<std::string> 函数定义;
					std::string 函数变量声明;
					std::string 实现代码 = f_NT_编译节点树(m_子集节点树, 函数定义, 函数变量声明);


					shader_code += 函数变量声明;
					for (auto& e : 函数定义) {
						shader_code += e;
					}

					shader_code += "void main() {\n";

					shader_code += "vec3 boundOffset        = gGeom[callSceneData.InstanceIndex].boundOffset;\n";
					shader_code += "vec3 boundSize          = gGeom[callSceneData.InstanceIndex].boundSize;\n";
					shader_code += "vec3 bound_uv           = (callSceneData.Vert - boundOffset) / boundSize;\n";
					//shader_code += "B_Faces       mesh_face = B_Faces(Resource_ObMesh.m_AddressFaces);\n";

					shader_code += f_着色器引用数据声明();
					//shader_code += "B_Indexs uv_index = B_Indexs(Resource_ObMesh.m_AddressUVIndex);\n";
					shader_code += 实现代码;


					std::vector<C_节点基类*> outNodes;
					f_get子集输出节点(outNodes);
					shader_code += f_着色器输出参数代码构建(outNodes, m_Code);

					shader_code += "}\n";


					FILE* f = fopen(着色文件路径.c_str(), "w");
					if (f) {
						//std::vector<int32> spvCode;
						//spvCode.assign(shader_code.begin(), shader_code.end());
						f_file_保存文本(f, shader_code);
						fclose(f);
					}


					std::string cmd = S_引擎::m_着色器编译器路径;
					cmd += " -V " + 着色文件路径;
					cmd += " -o " + SPV;
					cmd += " -I" + S_引擎::m_着色器头文件路径;
					cmd += " --target-env vulkan1.3";

					err = system(cmd.c_str());
					std::cout << "线程1 : " << err << std::endl;
				}


				if (!err) {
					f_bd_安装光追材质着色器(f_NodeCtx_get默认场景()->m_光追后端, m_子集节点树->m_ID, SPV, m_子集节点树->m_ID);
					std::cout << "编译着色器" << std::endl;
				}
			}
		}

	}


	
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}

	释放 += m_ReleaseCode;
	return m_Code;
}

void C_PBR材着色器节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_PBR材着色器节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

void C_PBR材着色器节点::f_入回收() {
	m_子集节点树->m_节点树绑定的父节点.erase(this);
	if (m_子集节点树->m_节点树绑定的父节点.size() == 0) {
		

		uint32 num = S_节点数据::g_着色节点树.size();
		for (uint32 i = 0; i < num; ++i) {
			if (S_节点数据::g_着色节点树[i].m_Ptr == m_子集节点树) {
				S_节点数据::g_着色节点树.erase(S_节点数据::g_着色节点树.begin() + i);
				f_bd_删除光追材质着色器(f_NodeCtx_get默认场景()->m_光追后端, i);
				break;
			}
		}
		
	}
}

void C_PBR材着色器节点::f_回收() {
	f_绑定子集节点树(m_子集节点树);
}

C_节点基类* f_node_创建设置PBR材质属性节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_PBR材着色器节点(ctx, 子节点树);
}

C_节点基类* f_node_加载设置PBR材质属性节点(S_设备环境& ctx, FILE* f) {
	std::wstring 链接的节点树名称 = f_file_读取字符串(f);

	C_节点树* tree = nullptr;
	if (S_节点数据::G用于重新映射节点树到节点的容器.find(链接的节点树名称) == S_节点数据::G用于重新映射节点树到节点的容器.end()) {
		f_node_加载节点树(ctx, f);
	}

	C_PBR材着色器节点* node = new C_PBR材着色器节点(ctx, S_节点数据::G用于重新映射节点树到节点的容器[链接的节点树名称]);
	return node;
}

void f_node_保存设置PBR材质属性节点(C_节点基类* n, FILE* f) {
	C_PBR材着色器节点* node = dynamic_cast<C_PBR材着色器节点*>(n);

	auto* tree = node->f_get子集树();
	f_file_保存字符串(f, tree->m_IDName);

	if (tree->m_未保存或加载) {
		tree->m_未保存或加载 = false;

		std::vector<C_节点树*> trees = { tree };
		f_node_保存节点树(trees, f);
	}
}





C_基于物理计算着色节点::C_基于物理计算着色节点(S_设备环境& ctx) : C_节点基类(DEF_基于物理计算着色节点, E_节点类型::e_节点Type_自定义) {
	m_Name = L"基于物理计算";
	m_Ctx = ctx;

	C_插座基类* socket;

	DEF_创建Vec3插座_I(L"color", nullptr);
	DEF_创建Vec3插座_I(L"emission", nullptr);
	DEF_创建F32插座_I(L"reflect", nullptr);
	DEF_创建F32插座_I(L"折射", nullptr);
	DEF_创建F32插座_I(L"粗糙", nullptr);
	DEF_创建F32插座_I(L"透明", nullptr);
	DEF_创建Vec3插座_I(L"法线", nullptr);
	//DEF_创建纹理_1D插座_I(L"颜色");

	DEF_创建Vec3插座_O(L"输出颜色");
	DEF_创建F32插座_O(L"反射", nullptr);



	m_外部加载 = f_alloc_BoolProp(nullptr, L"外部加载");
	m_外部加载.m_私有 = true;
	f_prop_Bool(m_外部加载) = false;

	//m_代码文件路径 = f_alloc_PathProp(nullptr, L"文件路径");
	//m_代码文件路径.m_私有 = true;


	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(1));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(2));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(3));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(4));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(5));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(6));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(7));
}

C_基于物理计算着色节点::~C_基于物理计算着色节点() {
	f_prop_Release(m_外部加载);
	//f_prop_Release(m_代码文件路径);
}

bool C_基于物理计算着色节点::f_update() {
	return false;
}

std::string C_基于物理计算着色节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	if (f_prop_Bool(m_外部加载)) {

	}
	else {
		uint32 inNum = f_get输入插座Num();
		for (uint32 i = 0; i < inNum; ++i) {
			m_Code += f_get输入插座(i)->f_构建变量代码(0);
		}

		auto name = f_getName();

		auto socket1 = f_get输入插座(1);
		auto socket2 = f_get输入插座(2);
		auto socket3 = f_get输入插座(3);
		auto socket4 = f_get输入插座(4);
		auto socket5 = f_get输入插座(5);
		
		if (socket1->f_isLink()) {
			//m_Code += "callMaterial.m_color = " + socket->f_getCode() + ";\n";
			//m_Code += "vec3 Color = " + socket->f_getCode() + ";\n";
		}
		//m_Code += "{ vec3 _temp_PBR_Color_ = "     + socket1->f_getCode() + ";\n";
		
		m_Code += "material.m_color = "     + socket1->f_getCode(0) + ";\n";
		m_Code += "material.m_emission = "  + socket2->f_getCode(0) + ";\n";
		m_Code += "material.m_reflect = "   + socket3->f_getCode(0) + ";\n";
		//m_Code += "material.m_refract = "   + socket4->f_getCode() + ";\n";
		//m_Code += "material.m_roughness = " + socket5->f_getCode() + ";\n";
		//m_Code += "material.m_alpha = "     + f_get输入插座(6)->f_getCode() + ";\n";
		//m_Code += "material.m_normal = "    + f_get输入插座(7)->f_getCode() + ";\n";

		//m_Code += "vec3 LigthDir = normalize(vec3(1,1,1));\n";
		m_Code += "vec3 " + name + " = f_MaterialPBR_calc(material, callSceneData.rayDir, callSceneData);\n";

		f_get输出插座(1)->f_setCode(name);
		

		if (socket1->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(socket1->m_GPU缓存) = DEF_Vec3插座数据(socket1);
			//((vec3*)socket1->m_GPU缓存->m_mappedPtr)[socket1->m_GPU内存偏移] = *DEF_Vec3插座数据(socket1, 0);
		}
		if (socket2->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(socket2->m_GPU缓存) = DEF_Vec3插座数据(socket2);
			//((vec3*)socket1->m_GPU缓存->m_mappedPtr)[socket2->m_GPU内存偏移] = *DEF_Vec3插座数据(socket2, 0);
		}
		if (socket3->m_GPU缓存.m_Buf) {
			f_buf_F32_at(socket3->m_GPU缓存) = DEF_F32插座数据(socket3);
			//((float32*)socket3->m_GPU缓存->m_mappedPtr)[socket3->m_GPU内存偏移] = *DEF_F32插座数据(socket3, 0);
		}
		if (socket4->m_GPU缓存.m_Buf) {
			f_buf_F32_at(socket4->m_GPU缓存) = DEF_F32插座数据(socket4);
			//((float32*)socket4->m_GPU缓存->m_mappedPtr)[socket4->m_GPU内存偏移] = *DEF_F32插座数据(socket4, 0);
		}
		if (socket5->m_GPU缓存.m_Buf) {
			f_buf_F32_at(socket5->m_GPU缓存) = DEF_F32插座数据(socket5);
			//((float32*)socket5->m_GPU缓存->m_mappedPtr)[socket5->m_GPU内存偏移] = *DEF_F32插座数据(socket5, 0);
		}
	}

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_基于物理计算着色节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_基于物理计算着色节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建基于物理计算着色节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_基于物理计算着色节点(ctx);
}

C_节点基类* f_node_加载基于物理计算着色节点(S_设备环境& ctx, FILE* f) {
	C_基于物理计算着色节点* node = new C_基于物理计算着色节点(ctx);
	return node;
}

void f_node_保存基于物理计算着色节点(C_节点基类* n, FILE* f) {
	C_基于物理计算着色节点* node = dynamic_cast<C_基于物理计算着色节点*>(n);
}










C_几何数据节点::C_几何数据节点(S_设备环境& ctx) : C_节点基类(DEF_几何数据节点, E_节点类型::e_节点Type_自定义) {
	m_Name = L"几何数据";
	m_Ctx = ctx;

	C_插座基类* socket;

	DEF_创建Vec3插座_O(L"顶点", nullptr);
	DEF_创建Vec3插座_O(L"法线", nullptr);
	DEF_创建Vec3插座_O(L"边界UV", nullptr);
	DEF_创建Vec3插座_O(L"大小", nullptr);
	DEF_创建Vec3插座_O(L"重心", nullptr);

}

C_几何数据节点::~C_几何数据节点() {
}

bool C_几何数据节点::f_update() {
	return false;
}

std::string C_几何数据节点::DEF_节点编译函数 {
	m_Code = "";
	m_ReleaseCode = "";

	//uint32 inNum = f_get输入插座Num();
	//for (uint32 i = 0; i < inNum; ++i) {
	//	m_Code += f_get输入插座(i)->f_构建变量代码();
	//}

	auto socket1 = f_get输出插座(1);
	auto socket2 = f_get输出插座(2);
	auto socket3 = f_get输出插座(3);
	auto socket4 = f_get输出插座(4);
	auto socket5 = f_get输出插座(5);

	socket1->f_setCode("callSceneData.Vert");
	socket2->f_setCode("callSceneData.Normal");
	socket3->f_setCode("bound_uv");
	socket4->f_setCode("boundSize");
	socket5->f_setCode("callSceneData.barycentrics");
	

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_几何数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_几何数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建几何数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_几何数据节点(ctx);
}

C_节点基类* f_node_加载几何数据节点(S_设备环境& ctx, FILE* f) {
	C_几何数据节点* node = new C_几何数据节点(ctx);
	return node;
}

void f_node_保存几何数据节点(C_节点基类* n, FILE* f) {
	C_几何数据节点* node = dynamic_cast<C_几何数据节点*>(n);
}







C_光线数据节点::C_光线数据节点(S_设备环境& ctx) : C_节点基类(DEF_光线数据节点, E_节点类型::e_节点Type_自定义) {
	m_Name = L"光线数据";
	m_Ctx = ctx;

	C_插座基类* socket;

	DEF_创建Vec3插座_O(L"颜色", nullptr);
	DEF_创建Vec3插座_O(L"射线", nullptr);
	DEF_创建Vec3插座_O(L"光线", nullptr);
	DEF_创建F32插座_O(L"强度", nullptr);
	DEF_创建F32插座_O(L"距离", nullptr);
}

C_光线数据节点::~C_光线数据节点() {
}

bool C_光线数据节点::f_update() {
	return false;
}

std::string C_光线数据节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	//std::string name = f_getName();
	
	auto* rt = f_getThis节点树();
	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		f_get输出插座(1)->f_setCode("callSceneData.Color");
		f_get输出插座(2)->f_setCode("callSceneData.rayDir");
		f_get输出插座(3)->f_setCode("callSceneData.ligthDir");
		f_get输出插座(4)->f_setCode("callSceneData.irradiance");
		f_get输出插座(5)->f_setCode("callSceneData.rayDir");
		break;
	}
	default:
		break;
	}
	//f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_光线数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_光线数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建光线数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_光线数据节点(ctx);
}

C_节点基类* f_node_加载光线数据节点(S_设备环境& ctx, FILE* f) {
	C_光线数据节点* node = new C_光线数据节点(ctx);
	return node;
}

void f_node_保存光线数据节点(C_节点基类* n, FILE* f) {
	C_光线数据节点* node = dynamic_cast<C_光线数据节点*>(n);
}




C_几何UV数据节点::C_几何UV数据节点(S_设备环境& ctx) : C_节点基类(DEF_几何UV数据节点) {
	m_Name = L"UV";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3插座_I(L"采样坐标", nullptr);
	DEF_创建I32插座_I(L"层");

	DEF_创建Vec3插座_O(L"UV", nullptr);

	m_UV类型 = f_alloc_EnumProp(nullptr, {
		{L"纹理坐标"},
		{L"等距圆柱"},
	}, L"UV类型");
	m_UV类型.m_私有 = true;

	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(1));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(2));
	f_构建代码_分配渲染器GPU属性变量(m_UV类型);

}

C_几何UV数据节点::~C_几何UV数据节点() {
	f_构建代码_释放渲染器GPU插座变量(*f_get输入插座(1));
	f_构建代码_释放渲染器GPU插座变量(*f_get输入插座(2));
	f_构建代码_释放渲染器GPU属性变量(m_UV类型);
}

bool C_几何UV数据节点::f_update() {
	return false;
}

std::string C_几何UV数据节点::DEF_节点编译函数 {
	m_Code = "";
    m_ReleaseCode = "";
	std::string name = f_getName();


	f_buf_I32_at(m_UV类型.m_GPU缓存[0],0) = f_prop_enum(m_UV类型);

	m_Code += "vec3 " + name + " = vec3(0);\n";
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	auto* rt = f_getThis节点树();
	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		m_Code += "switch(" + f_代码构建_i32GPU变量(m_UV类型) + "){\n";
		m_Code += "case 0:{\n";

		m_Code += "if(" + socket2->f_getCode(0) + " >= gGeom[callSceneData.InstanceIndex].uvLayerNum) break;\n";

		m_Code += "uvec3 uvIndex = uvec3(1);\n";
		m_Code += "switch(" + socket2->f_getCode(0) + "){\n";
		m_Code += "case 0: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset0 ]; break;\n";
		m_Code += "case 1: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset1 ]; break;\n";
		m_Code += "case 2: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset2 ]; break;\n";
		m_Code += "case 3: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset3 ]; break;\n";
		m_Code += "case 4: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset4 ]; break;\n";
		m_Code += "case 5: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset5 ]; break;\n";
		m_Code += "case 6: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset6 ]; break;\n";
		m_Code += "case 7: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset7 ]; break;\n";
		//m_Code += "case 0: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex ]; break;\n";
		//m_Code += "case 1: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex ]; break;\n";
		//m_Code += "case 2: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex ]; break;\n";
		//m_Code += "case 3: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex ]; break;\n";
		//m_Code += "case 4: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex ]; break;\n";
		//m_Code += "case 5: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex ]; break;\n";
		//m_Code += "case 6: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex ]; break;\n";
		//m_Code += "case 7: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex ]; break;\n";
		m_Code += "}\n";
		//m_Code += "uvec3 uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex ];\n";
		m_Code += "vec2 uvX = mesh_uv.UV[ uvIndex.x ];\n";
		m_Code += "vec2 uvY = mesh_uv.UV[ uvIndex.y ];\n";
		m_Code += "vec2 uvZ = mesh_uv.UV[ uvIndex.z ];\n";
		m_Code += name + ".xy = uvX * callSceneData.barycentrics.x + uvY * callSceneData.barycentrics.y + uvZ * callSceneData.barycentrics.z;\n";
		m_Code += name + ".z = 0;\n";
		//m_Code += name + ".xy = uvX;\n";
		//m_Code += name + ".xyz = vec3(uvIndex)*0.02;\n";
		//m_Code += name + ".xyz = vec3(callSceneData.barycentrics);\n";
		//m_Code += name + ".xyz = vec3(uvX, 0);\n";
		//m_Code += name + ".xyz = vec3(callSceneData.GeometryIndex);\n";
		m_Code += "break;\n";
		m_Code += "}\n";
		
		m_Code += "case 1:\n";
		m_Code += name + ".xy = " + DEF_S(f_equirectangularUV)"(" + socket1->f_getCode(0) + ");\n";
		m_Code += "break;\n";
		m_Code += "}\n";

		m_Code += name + ".y = (-" + name + ".y) + 1;\n";

		if (socket2->m_GPU缓存.m_Buf) {
			f_buf_I32_at(socket2->m_GPU缓存, 0) = DEF_I32插座数据(socket2);
		}
		break;
	}
	default:
		break;
	}

	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_几何UV数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_UV类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_几何UV数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_UV类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建几何UV数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_几何UV数据节点(ctx);
}

C_节点基类* f_node_加载几何UV数据节点(S_设备环境& ctx, FILE* f) {
	C_几何UV数据节点* node = new C_几何UV数据节点(ctx);
	return node;
}

void f_node_保存几何UV数据节点(C_节点基类* n, FILE* f) {
	C_几何UV数据节点* node = dynamic_cast<C_几何UV数据节点*>(n);
}

